<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
    
  <meta name="description" content="林湃滨的个人博客" />
  
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
  <title>
    【框架】SpringCloud总结 |  滨书
  </title>
  <meta name="generator" content="hexo-theme-yilia-plus">
  
  <link rel="shortcut icon" href="/favicon.ico" />
  
  
<link rel="stylesheet" href="/css/style.css">

  
<script src="/js/pace.min.js"></script>


  

  

<link rel="alternate" href="/atom.xml" title="滨书" type="application/atom+xml">
</head>

</html>

<body>
  <div id="app">
    <main class="content">
      <section class="outer">
  <article id="post-JavaFrame/SpringCloudIntroduction" class="article article-type-post" itemscope
  itemprop="blogPost" data-scroll-reveal>

  <div class="article-inner">
    
    <header class="article-header">
       
<h1 class="article-title sea-center" style="border-left:0" itemprop="name">
  【框架】SpringCloud总结
</h1>
  

    </header>
    

    
    <div class="article-meta">
      <a href="/2019/10/15/JavaFrame/SpringCloudIntroduction/" class="article-date">
  <time datetime="2019-10-15T03:44:46.000Z" itemprop="datePublished">2019-10-15</time>
</a>
      
  <div class="article-category">
    <a class="article-category-link" href="/categories/JavaFrame/">JavaFrame</a>
  </div>

      
      
<div class="word_count">
    <span class="post-time">
        <span class="post-meta-item-icon">
            <i class="ri-quill-pen-line"></i>
            <span class="post-meta-item-text"> 字数统计:</span>
            <span class="post-count">3.7k字</span>
        </span>
    </span>

    <span class="post-time">
        &nbsp; | &nbsp;
        <span class="post-meta-item-icon">
            <i class="ri-book-open-line"></i>
            <span class="post-meta-item-text"> 阅读时长≈</span>
            <span class="post-count">14分钟</span>
        </span>
    </span>
</div>

      
    </div>
    

    
    
    <div class="tocbot"></div>





    

    <div class="article-entry" itemprop="articleBody">
      


      

      
      <h1 id="SpringCloud"><a href="#SpringCloud" class="headerlink" title="SpringCloud"></a>SpringCloud</h1><h2 id="1、单体架构系统与分布式集群"><a href="#1、单体架构系统与分布式集群" class="headerlink" title="1、单体架构系统与分布式集群"></a>1、单体架构系统与分布式集群</h2><h3 id="单体架构系统"><a href="#单体架构系统" class="headerlink" title="单体架构系统"></a>单体架构系统</h3><p>单体架构便是将所有功能都放于一个应用之中。</p>
<p>单体架构系统的特点：</p>
<ul>
<li><p>好处：便于开发、测试、部署也方便，直接打包成jar或war便可。</p>
</li>
<li><p>弊端：高访问，高并发的上限是固定的。 </p>
<blockquote>
<p>比如一个单体架构，能够承受 1000次访问/秒。 但是访问量达到 2000次/秒的时候，就会非常卡顿，严重影响业务，并且仅仅依靠单体架构本身，很难突破这个瓶颈了。</p>
</blockquote>
</li>
</ul>
<h3 id="分布式和集群"><a href="#分布式和集群" class="headerlink" title="分布式和集群"></a>分布式和集群</h3><p>打破单体架构性能瓶颈的问题，</p>
<h2 id="2、微服务的特点"><a href="#2、微服务的特点" class="headerlink" title="2、微服务的特点"></a>2、微服务的特点</h2><h3 id="好处"><a href="#好处" class="headerlink" title="好处"></a>好处</h3><p><strong>技术异构性:</strong></p>
<p>在一个由多个服务相互协作的系统中,可以在不同的服务中使用最适合该服务的技术</p>
<p><strong>弹性:</strong></p>
<p>如果系统中的一个组件不可用了,但并没有导致级联故障,那么系统的其他部分还可以正常运行</p>
<p><strong>扩展:</strong></p>
<p>可以只对那些需要扩属的服务进行扩属</p>
<p><strong>简化部害:</strong></p>
<p>各个服务的部署是独立的,这样就可以更快地对特定部分的代码进行部<br>·与组织结构相匹配:可以很好地将架构与组织结构相匹配,避免出现过大的代码库,从而得凖想团队大小及生产力</p>
<p>可组合性:</p>
<p>不同服务模块的接口可以再进行重用,成为其他产品中的一个组件</p>
<p><strong>对可替代性的优化:</strong></p>
<p>可以在需要时轻易地重写服务,或者删除不再使用的服务</p>
<h3 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h3><p>1.<strong>运维开销更多的服务也就麻味着更多的运维</strong>,产品团队需要保证所有的相关服务都有完善的监控等基础设施,传统的架构开发者只需要保证一个应用正常运行,而现在却需要保证几十甚至上百道工序高效运转，这是一个艰巨的任务</p>
<p>Devops要求使用微服务架构后,开发团队需要保证一个 Tomcat集群可用,保证一个数据库可用,这就味团队需要高品质的 Devops和自动化技术,而现在,这样的全栈式人才很少,</p>
<p>隐式接口<strong>服务和服务之间通过接口来联系</strong>,当某一个服务更改接口格式时,可能涉及到此接口的所有服<br>务都需要做调整</p>
<p><strong>重复劳动</strong>在很多服务中可能都会使用到同一个功能,而这一功能点投有足够大到提供一个服务的程度,这个时候可能不同的服务团队都会单独开发这一D能,的业务逻,这压背了良好的件工程中的很多</p>
<h2 id="SpringCloud和Dubbo的区别"><a href="#SpringCloud和Dubbo的区别" class="headerlink" title="SpringCloud和Dubbo的区别"></a>SpringCloud和Dubbo的区别</h2><p><img src="https://www.bjsxt.com/wp-content/themes/sxt/statics/images/bjsxt/javamianshiti/images/javaimg41.png" alt=""></p>
<h2 id="SpringCloud基本组件"><a href="#SpringCloud基本组件" class="headerlink" title="SpringCloud基本组件"></a>SpringCloud基本组件</h2><h3 id="1、SpringCloud-Eureka：注册发现中心"><a href="#1、SpringCloud-Eureka：注册发现中心" class="headerlink" title="1、SpringCloud Eureka：注册发现中心"></a>1、SpringCloud Eureka：注册发现中心</h3><h4 id="1-1、建立服务注册与发现中心：eureka-server"><a href="#1-1、建立服务注册与发现中心：eureka-server" class="headerlink" title="1.1、建立服务注册与发现中心：eureka server"></a>1.1、建立服务注册与发现中心：eureka server</h4><ol>
<li>Spring Initializr-》勾选 Eureka Server依赖 ，进行创建注册发现server模块</li>
</ol>
<p>查看pom.xml珠主要内容</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">properties</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">java.version</span>&gt;</span>1.8<span class="tag">&lt;/<span class="name">java.version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">spring-cloud.version</span>&gt;</span>Greenwich.SR3<span class="tag">&lt;/<span class="name">spring-cloud.version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">properties</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-netflix-eureka-client<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencyManagement</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-dependencies<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;spring-cloud.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">type</span>&gt;</span>pom<span class="tag">&lt;/<span class="name">type</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">scope</span>&gt;</span>import<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencyManagement</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br></pre></td></tr></table></figure>

<ol start="2">
<li>application.yml内容</li>
</ol>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">### 当前服务的名称</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">eureka-server</span></span><br><span class="line">  <span class="comment">###指定端口</span></span><br><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br><span class="line"></span><br><span class="line"><span class="attr">eureka:</span></span><br><span class="line">  <span class="attr">instance:</span></span><br><span class="line">    <span class="comment">###指定注册地址</span></span><br><span class="line">    <span class="attr">hostname:</span> <span class="string">localhost</span></span><br><span class="line">  <span class="attr">client:</span></span><br><span class="line">    <span class="attr">service-url:</span></span><br><span class="line">      <span class="attr">defaultZone:</span> <span class="string">http://$&#123;eureka.instance.hostname&#125;:$&#123;server.port&#125;/eureka/</span></span><br><span class="line">    <span class="attr">register-with-eureka:</span> <span class="literal">false</span></span><br><span class="line">    <span class="attr">fetch-registry:</span> <span class="literal">false</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>在运行类中需要加上一个@EnableEurekaServer注解，说明这是一个 服务注册发现 的eureka server</p>
</blockquote>
<h4 id="1-2、建立各个微服务client"><a href="#1-2、建立各个微服务client" class="headerlink" title="1.2、建立各个微服务client"></a>1.2、建立各个微服务client</h4><ol>
<li><p>Spring Initializr-》勾选Spring Web、 Eureka Client依赖 ，进行创建微服务模块</p>
<p>查看pom.xml文件主要内容：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">properties</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">java.version</span>&gt;</span>1.8<span class="tag">&lt;/<span class="name">java.version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">spring-cloud.version</span>&gt;</span>Greenwich.SR3<span class="tag">&lt;/<span class="name">spring-cloud.version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">properties</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-netflix-eureka-client<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencyManagement</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-dependencies<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;spring-cloud.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">type</span>&gt;</span>pom<span class="tag">&lt;/<span class="name">type</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">scope</span>&gt;</span>import<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencyManagement</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br></pre></td></tr></table></figure>



</li>
</ol>
<ol start="2">
<li><p>application.yml</p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">### 当前服务的名称</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">eureka-grade</span></span><br><span class="line">  <span class="comment">### 指定端口</span></span><br><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8081</span></span><br><span class="line"></span><br><span class="line"><span class="attr">eureka:</span></span><br><span class="line">  <span class="attr">client:</span></span><br><span class="line">    <span class="attr">service-url:</span></span><br><span class="line">      <span class="attr">defaultZone:</span> <span class="string">http://localhost:8080/eureka/</span></span><br><span class="line">    <span class="attr">register-with-eureka:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">fetch-registry:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>需要在运行类中配置@EnableEurekaClient注解，实现注解</p>
</blockquote>
</li>
</ol>
<h4 id="1-3、实现各个服务之间的通信"><a href="#1-3、实现各个服务之间的通信" class="headerlink" title="1.3、实现各个服务之间的通信"></a>1.3、实现各个服务之间的通信</h4><ol>
<li><p>resttemplate实现微服务之间的调用：</p>
<p>Application类中向IOC容器中注册一个RestTemplate的bean</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 在Ioc容器中注册一个restTemplate的bean</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="meta">@LoadBalanced</span>   <span class="comment">//负载均衡</span></span><br><span class="line">    <span class="function">RestTemplate <span class="title">restTemplate</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> RestTemplate();</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>



</li>
</ol>
<p>   在Service层中通过RestTemplate实现对其他微服务发起请求</p>
   <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">StudentService</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> RestTemplate restTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getGrade</span><span class="params">(Integer id)</span> </span>&#123;</span><br><span class="line">        String url = <span class="string">"http://eureka-grade/get/&#123;id&#125;"</span>;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 第一个参数为请求的url</span></span><br><span class="line"><span class="comment">         * 第二个参数为返回的值类型</span></span><br><span class="line"><span class="comment">         * 第三个参数为 Object... uriVariables参数</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="keyword">return</span> restTemplate.getForObject(url , String<span class="class">.<span class="keyword">class</span>,<span class="title">id</span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>   在Controller中调用Service，对其他微服务进行请求：</p>
   <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">StudentController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> StudentService studentService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping</span>(<span class="string">"/getMsg"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getMsg</span><span class="params">(String name,Integer id)</span></span>&#123;</span><br><span class="line">        String gradeMsg = studentService.getGrade(id);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> name + <span class="string">"是"</span> + gradeMsg;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<ol start="2">
<li><p>Feign</p>
<p>Feign是SpringCloud 中服务Client端的调用框架，通常与ribbon(负载均衡)，hystrix(断路器)组合使用。</p>
<p>在某些项目中，由于遗留原因，整个系统并不是spring cloud项目，甚至不是spring项目，而使用者关注的重点仅仅是简化http调用代码的编写。</p>
<p>如果采用httpclient或者okhttp这样相对较重的框架，对初学者来说编码量与学习曲线都会是一个挑战，而使用spring中RestTemplate，又没有配置化的解决方案，由此想到是否可以脱离spring cloud，独立使用Feign。</p>
<ul>
<li>Maven依赖</li>
</ul>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;com.netflix.feign&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;feign-core&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;8.18.0&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>



</li>
</ol>
<ul>
<li><p>自定义接口</p>
<p>通过@RequestLine指定HTTP协议和URL地址</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> feign.Param;</span><br><span class="line"><span class="keyword">import</span> feign.RequestLine;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">RemoteService</span> </span>&#123;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@RequestLine</span>(<span class="string">"GET /users/list?name=&#123;name&#125;"</span>)</span><br><span class="line">    <span class="function">String <span class="title">getOwner</span><span class="params">(@Param(value = <span class="string">"name"</span>)</span> String name)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



</li>
</ul>
<ul>
<li><p>配置类</p>
<p>options方法指定<strong>连接超时时长</strong>及<strong>响应超时时长</strong>，retryer方法指定重试策略,target方法绑定接口与服务端地址。返回类型为绑定的接口类型。</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">RemoteService service = Feign.builder()</span><br><span class="line">            .options(<span class="keyword">new</span> Options(<span class="number">1000</span>, <span class="number">3500</span>))</span><br><span class="line">            .retryer(<span class="keyword">new</span> Retryer.Default(<span class="number">5000</span>, <span class="number">5000</span>, <span class="number">3</span>))</span><br><span class="line">            .target(RemoteService.class, "http://127.0.0.1:8085");</span><br></pre></td></tr></table></figure>



</li>
</ul>
<ul>
<li><p>调用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">String result = service.getOwner(<span class="string">"scott"</span>);</span><br></pre></td></tr></table></figure>



</li>
</ul>
<ul>
<li><p>业务接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">RemoteService</span></span>&#123;</span><br><span class="line">    <span class="meta">@Header</span>(&#123;<span class="string">"Content-Type:application/json"</span>,<span class="string">"Accept:application/json"</span>&#125;)</span><br><span class="line">    <span class="meta">@RequestLine</span>(<span class="string">"POST /user/list"</span>)</span><br><span class="line">    <span class="function">User <span class="title">getOwner</span><span class="params">(User user)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



</li>
</ul>
<ul>
<li><p>配置</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">RemoteService service = Feign.builder()</span><br><span class="line">    .encoder(<span class="keyword">new</span> JacksonEncoder())			<span class="comment">//对象编码方式</span></span><br><span class="line">    .decoder(<span class="keyword">new</span> JacksonDecoder())			<span class="comment">//对象解码方式</span></span><br><span class="line">    .options(<span class="keyword">new</span> Options(<span class="number">1000</span>,<span class="number">3500</span>))		<span class="comment">//</span></span><br><span class="line">    .retryer(<span class="keyword">new</span> Retryer.Default(<span class="number">5000</span>,<span class="number">5000</span>,<span class="number">3</span>))</span><br><span class="line">    .target(RemoteService.class,"http://127.0.0.1:8085");</span><br></pre></td></tr></table></figure>







</li>
</ul>
<h3 id="2、SpringCloud-Ribbon：负载均衡"><a href="#2、SpringCloud-Ribbon：负载均衡" class="headerlink" title="2、SpringCloud Ribbon：负载均衡"></a>2、SpringCloud Ribbon：负载均衡</h3><p>​    Ribbon 是一个基于Http和TCP的客服端负载均衡工具，它是基于Netflix Ribbon实现的。</p>
<p>​    它不像spring cloud服务注册中心、配置中心、API网关那样独立部署，但是它几乎存在于每个spring cloud 微服务中。包括feign提供的声明式服务调用也是基于该Ribbon实现的。</p>
<p>​    ribbon默认提供很多种负载均衡算法，例如 轮询、随机 等等。甚至包含自定义的负载均衡算法。</p>
<p>用来实现客户端的负载均衡，支持http和udp的传输协议。无缝衔接eureka（同一家公司开发的）</p>
<p>核心：</p>
<ul>
<li>服务发现：发现依赖服务的列表</li>
<li>服务选择规则：在多个服务中如何选择一个有效服务</li>
<li>服务监听：检测失效的服务，剔除失效服务</li>
</ul>
<p>负载均衡方案：</p>
<p>第一类：集中式负载均衡, 即在consumer和provider之间使用独立的负载均衡设施(可以是硬件，如F5, 也可以是软件，如nginx), 由该设施负责把 访问请求 通过某种策略转发至provider；</p>
<p>第二类：进程内负载均衡，将负载均衡逻辑集成到consumer，consumer从服务注册中心获知有哪些地址可用，然后自己再从这些地址中选择出一个合适的provider。</p>
<p>Ribbon就属于后者，它只是一个类库，集成于consumer进程，consumer通过它来获取到provider的地址。</p>
<p>常见的负载均衡策略：</p>
<table>
<thead>
<tr>
<th>id</th>
<th>策略名称</th>
<th>策略对应的类名</th>
<th>实现原理</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>轮询策略（默认）</td>
<td>RoundRobinRule</td>
<td>轮询策略表示每次都顺序取下一个provider，比如一共有5个provider，第1次取第1个，第2次取第2个，第3次取第3个，以此类推</td>
</tr>
<tr>
<td>2</td>
<td>权重轮询策略</td>
<td>WeightedResponseTimeRule</td>
<td>1.根据每个provider的响应时间分配一个权重，响应时间越长，权重越小，被选中的可能性越低。<br> 2.原理：一开始为轮询策略，并开启一个计时器，每30秒收集一次每个provider的平均响应时间，当信息足够时，给每个provider附上一个权重，并按权重随机选择provider，高权越重的provider会被高概率选中。</td>
</tr>
<tr>
<td>3</td>
<td>随机策略</td>
<td>RandomRule</td>
<td>从provider列表中随机选择一个provider</td>
</tr>
<tr>
<td>4</td>
<td>最少并发数策略</td>
<td>BestAvailableRule</td>
<td>选择正在请求中的<strong>并发数最小</strong>的provider，除非这个provider在熔断中。</td>
</tr>
<tr>
<td>5</td>
<td>在“选定的负载均衡策略”基础上进行重试机制</td>
<td>RetryRule</td>
<td>1.“选定的负载均衡策略”这个策略是轮询策略RoundRobinRule <br>2.该重试策略先设定一个阈值时间段，如果在这个阈值时间段内当选择provider不成功，则一直尝试采用“选定的负载均衡策略：轮询策略”最后选择一个可用的provider</td>
</tr>
<tr>
<td>6</td>
<td>可用性敏感策略</td>
<td>AvailabilityFilteringRule</td>
<td>过滤性能差的provider,有2种： <br>第一种：过滤掉在eureka中处于一直连接失败provider <br>第二种：过滤掉高并发的provider</td>
</tr>
<tr>
<td>7</td>
<td>区域敏感性策略</td>
<td>ZoneAvoidanceRule</td>
<td>1.以一个区域为单位考察可用性，对于不可用的区域整个丢弃，从剩下区域中选可用的provider <br>2.如果这个ip区域内有一个或多个实例不可达或响应变慢，都会降低该ip区域内其他ip被选中的权重。</td>
</tr>
</tbody></table>
<h3 id="3、SpringCloud-Feign"><a href="#3、SpringCloud-Feign" class="headerlink" title="3、SpringCloud Feign"></a>3、SpringCloud Feign</h3><p>Feign是一种声明式、模板化的HTTP客户端技术(仅在consumer中使用)。</p>
<h4 id="什么是声明式调用"><a href="#什么是声明式调用" class="headerlink" title="什么是声明式调用"></a>什么是声明式调用</h4><p>声明式调用就像调用本地方法一样调用远程方法;无感知远程http请求。</p>
<p>1、Spring Cloud的声明式调用, 可以做到使用 HTTP请求远程服务时能就像调用本地方法一样的体验，开发者完全感知不到这是远程方法，更感知不到这是个HTTP请求。</p>
<p>2、它像Dubbo一样，consumer直接调用接口方法调用provider，而不需要通过常规的Http Client构造请求再解析返回数据。</p>
<p>3、它解决了让开发者调用远程接口就跟调用本地方法一样，无需关注与远程的交互细节，更无需关注分布式环境开发。</p>
<h3 id="4、SpringCloud-Hystrix：断路器"><a href="#4、SpringCloud-Hystrix：断路器" class="headerlink" title="4、SpringCloud Hystrix：断路器"></a>4、SpringCloud Hystrix：断路器</h3><h3 id="5、SpringCloud-Config：分布式配置中心"><a href="#5、SpringCloud-Config：分布式配置中心" class="headerlink" title="5、SpringCloud Config：分布式配置中心"></a>5、SpringCloud Config：分布式配置中心</h3><p>为什么要使用springcloud config配置中心</p>
<p>springcloud config采用集中式的配置中心来管理每个服务的配置信息。springcloud config 配置中心在微服务分布式系统中，采用服务端和客户端来提供可拓展的配置服务，配置中心负责管理所有服务的各种环境配置文件。</p>
<p>配置中心默认采用git的方式存储配置文件，因此很容易部署和修改，有助于对环境配置进行版本管理。</p>
<p>配置中心config 解决了微服务配置的中心化、版本控制、平台独立、语言独立等问题。</p>
<p>config的特性：</p>
<ol>
<li>提供服务端和客户端的支持（springcloud config server 和 springcloud config client）</li>
<li>集中式管理分布式环境下的应用配置</li>
<li>基于Spring环境，与Spring集成</li>
<li>可用于任何语言开发的程序</li>
<li>默认实现基于git仓库的版本管理</li>
</ol>
<h3 id="6、SpringCloud-Zuul：服务网关"><a href="#6、SpringCloud-Zuul：服务网关" class="headerlink" title="6、SpringCloud Zuul：服务网关"></a>6、SpringCloud Zuul：服务网关</h3><p>网关服务，通常是外部访问服务的唯一接口，访问内部的所有服务都必须先经过网关服务。网关服务的主要功能是<strong>消息解析过滤，路由，转发</strong>等。</p>
<p>服务网关 = 路由转发 + 过滤器</p>
<ul>
<li>路由转发：接受一切外界请求，转发到后端的微服务中</li>
<li>过滤器：在服务网关中可以完成一系列的横切功能，如权限校验，限流以及监控等等，这些都可以通过过滤器实现（路由转发也是通过过滤器实现的）</li>
</ul>
<p>1、为什么需要服务网关</p>
<p>在微服务体系架构中，所谓的横切功能可以写在一下三个位置：</p>
<ul>
<li>每个服务自己进行实现</li>
<li>写到一个公共的服务中，其他需要的服务都依赖于这个服务</li>
<li>写到服务网关的前置过滤器中，所有请求过来都进行权限校验</li>
</ul>
<h3 id="7、SpringCloud-Bus：消息总线"><a href="#7、SpringCloud-Bus：消息总线" class="headerlink" title="7、SpringCloud Bus：消息总线"></a>7、SpringCloud Bus：消息总线</h3><p>SpringCloud Bus继承了市面上常用的消息代理（rabbit mq、kafka等），连接微服务系统中的所有节点，当有数据变更时候，可以通过消息代理通知微服务及时变更数据。</p>
<p>SpringCloud Bus解决的问题：</p>
<ol>
<li>微服务数据变更，及时同步的问题。</li>
</ol>
<h2 id="微服务架构的常用设计模式"><a href="#微服务架构的常用设计模式" class="headerlink" title="微服务架构的常用设计模式"></a>微服务架构的常用设计模式</h2><p>代理设计模式<br>聚合设计模式<br>链条设计模式<br>聚合链条设计模式<br>数据共享设计模式<br>异步消息设计模式</p>

      
      <!-- reward -->
      
      <div id="reward-btn">
        打赏
      </div>
      
    </div>
      <!-- copyright -->
      
        <div class="declare">
          <ul class="post-copyright">
            <li>
              <i class="ri-copyright-line"></i>
              <strong>版权声明： </strong s>
              本博客所有文章除特别声明外，均采用 <a href="https://www.apache.org/licenses/LICENSE-2.0.html" rel="external nofollow"
                target="_blank">Apache License 2.0</a> 许可协议。转载请注明出处！
            </li>
          </ul>
        </div>
        
    <footer class="article-footer">
      
          
<div class="share-btn">
      <span class="share-sns share-outer">
        <i class="ri-share-forward-line"></i>
        分享
      </span>
      <div class="share-wrap">
        <i class="arrow"></i>
        <div class="share-icons">
          
          <a class="weibo share-sns" href="javascript:;" data-type="weibo">
            <i class="ri-weibo-fill"></i>
          </a>
          <a class="weixin share-sns wxFab" href="javascript:;" data-type="weixin">
            <i class="ri-wechat-fill"></i>
          </a>
          <a class="qq share-sns" href="javascript:;" data-type="qq">
            <i class="ri-qq-fill"></i>
          </a>
          <a class="douban share-sns" href="javascript:;" data-type="douban">
            <i class="ri-douban-line"></i>
          </a>
          <!-- <a class="qzone share-sns" href="javascript:;" data-type="qzone">
            <i class="icon icon-qzone"></i>
          </a> -->
          
          <a class="facebook share-sns" href="javascript:;" data-type="facebook">
            <i class="ri-facebook-circle-fill"></i>
          </a>
          <a class="twitter share-sns" href="javascript:;" data-type="twitter">
            <i class="ri-twitter-fill"></i>
          </a>
          <a class="google share-sns" href="javascript:;" data-type="google">
            <i class="ri-google-fill"></i>
          </a>
        </div>
      </div>
</div>

<div class="wx-share-modal">
    <a class="modal-close" href="javascript:;"><i class="ri-close-circle-line"></i></a>
    <p>扫一扫，分享到微信</p>
    <div class="wx-qrcode">
      <img src="//api.qrserver.com/v1/create-qr-code/?size=150x150&data=https://linpaibin.gitee.io/2019/10/15/JavaFrame/SpringCloudIntroduction/" alt="微信分享二维码">
    </div>
</div>

<div id="share-mask"></div>
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/SpringCloud/" rel="tag">SpringCloud</a></li></ul>


    </footer>

  </div>

  
  
  <nav class="article-nav">
    
      <a href="/2019/10/16/Java/JavaMultiThread/" class="article-nav-link">
        <strong class="article-nav-caption">上一篇</strong>
        <div class="article-nav-title">
          
            【Java】多线程
          
        </div>
      </a>
    
    
  </nav>


  

  
  
<!-- valine评论 -->
<div id="vcomments-box">
    <div id="vcomments">
    </div>
</div>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src='https://cdn.jsdelivr.net/npm/valine@1.3.10/dist/Valine.min.js'></script>
<script>
    new Valine({
        el: '#vcomments',
        notify: false,
        verify: '',
        app_id: 'gtXNe43HVDH72a7XMn9zNgz8-gzGzoHsz',
        app_key: 'Df8WdcqcC2DCWL1pfcWb4QfN',
        path: window.location.pathname,
        avatar: 'mp',
        placeholder: '既然都来了，便留个爪印呗~_(¦3」∠)_',
        recordIP: true
    });
    const infoEle = document.querySelector('#vcomments .info');
    if (infoEle && infoEle.childNodes && infoEle.childNodes.length > 0) {
        infoEle.childNodes.forEach(function (item) {
            item.parentNode.removeChild(item);
        });
    }
</script>
<style>
    #vcomments-box {
        padding: 5px 30px;
    }

    @media screen and (max-width: 800px) {
        #vcomments-box {
            padding: 5px 0px;
        }
    }

    #vcomments-box #vcomments {
        background-color: #fff;
    }

    .v .vlist .vcard .vh {
        padding-right: 20px;
    }

    .v .vlist .vcard {
        padding-left: 10px;
    }
</style>

  

  
  
  

</article>
</section>
      <footer class="footer">
  <div class="outer">
    <ul class="list-inline">
      <li>
        &copy;
        2019-2020
        LinPaiBin
      </li>
      <li>
        
          Powered by
        
        
        <a href="https://hexo.io" target="_blank">Hexo</a> Theme <a href="https://github.com/Shen-Yu/hexo-theme-ayer" target="_blank">Ayer</a>
        
      </li>
    </ul>
    <ul class="list-inline">
      <li>
        
        
        <span>
  <i>PV:<span id="busuanzi_value_page_pv"></span></i>
  <i>UV:<span id="busuanzi_value_site_uv"></span></i>
</span>
        
      </li>
      <li>
        <!-- cnzz统计 -->
        
        <script type="text/javascript" src='https://s9.cnzz.com/z_stat.php?id=1278069914&amp;web_id=1278069914'></script>
        
      </li>
    </ul>
  </div>
</footer>
    <div class="to_top">
        <div class="totop" id="totop">
  <i class="ri-arrow-up-line"></i>
</div>
      </div>
    </main>
      <aside class="sidebar">
        <button class="navbar-toggle"></button>
<nav class="navbar" style="opacity: 0.5;">
  
  <div class="logo">
    <a href="/"><img src="/images/ayer-side.svg" alt="滨书"></a>
  </div>
  
  <ul class="nav nav-main">
    
    <li class="nav-item">
      <a class="nav-item-link" href="/">主页</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/archives">归档</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/categories">分类</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/tags">标签</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/tags/%E7%94%9F%E6%B4%BB/">生活</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/2019/12/02/AboutMe">关于我</a>
    </li>
    
  </ul>
</nav>
<nav class="navbar navbar-bottom">
  
  <ul class="nav">
    <li class="nav-item">
      
      <a class="nav-item-link nav-item-search"  title="Search">
        <i class="ri-search-line"></i>
      </a>
      
      
      <a class="nav-item-link" target="_blank" href="/atom.xml" title="RSS Feed">
        <i class="ri-rss-line"></i>
      </a>
      
    </li>
  </ul>
</nav>
<div class="search-form-wrap">
  <div class="local-search local-search-plugin">
  <input type="search" id="local-search-input" class="local-search-input" placeholder="Search...">
  <div id="local-search-result" class="local-search-result"></div>
</div>
</div>
      </aside>
      <div id="mask"></div>

<!-- #reward -->
<div id="reward">
  <span class="close"><i class="ri-close-line"></i></span>
  <p class="reward-p"><i class="ri-cup-line"></i>请我喝杯咖啡吧~</p>
  <div class="reward-box">
    
    <div class="reward-item">
      <img class="reward-img" src="/images/alipay.jpg">
      <span class="reward-type">支付宝</span>
    </div>
    
    
    <div class="reward-item">
      <img class="reward-img" src="/images/wechat.jpg">
      <span class="reward-type">微信</span>
    </div>
    
  </div>
</div>
      
<script src="/js/jquery-2.0.3.min.js"></script>


<script src="/js/jquery.justifiedGallery.min.js"></script>


<script src="/js/lazyload.min.js"></script>


<script src="/js/busuanzi-2.3.pure.min.js"></script>


<script src="/js/share.js"></script>



<script src="/fancybox/jquery.fancybox.min.js"></script>




<script>
  try {
    var typed = new Typed("#subtitle", {
    strings: ['人生如棋，吾愿为卒','愿你一生努力，一生无憾','不求事事顺意，但求无愧于心'],
    startDelay: 0,
    typeSpeed: 250,
    loop: true,
    backSpeed: 100,
    showCursor: true
    });
  } catch (err) {
  }
  
</script>




<script src="/js/tocbot.min.js"></script>

<script>
  // Tocbot_v4.7.0  http://tscanlin.github.io/tocbot/
  tocbot.init({
    tocSelector: '.tocbot',
    contentSelector: '.article-entry',
    headingSelector: 'h1, h2, h3, h4, h5, h6',
    hasInnerContainers: true,
    scrollSmooth: true,
    scrollContainer:'main',
    positionFixedSelector: '.tocbot',
    positionFixedClass: 'is-position-fixed',
    fixedSidebarOffset: 'auto',
    onClick: (e) => {
      $('.toc-link').removeClass('is-active-link');
      $(`a[href=${e.target.hash}]`).addClass('is-active-link');
      $(e.target.hash).scrollIntoView();
      return false;
    }
  });
</script>


<script>
  var ayerConfig = {
    mathjax: false
  }
</script>


<script src="/js/ayer.js"></script>


<script src="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.css">


<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">

    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>

    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">

        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>

        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">

            <div class="pswp__top-bar">

                <!--  Controls are self-explanatory. Order can be changed. -->

                <div class="pswp__counter"></div>

                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>

                <button class="pswp__button pswp__button--share" style="display:none" title="Share"></button>

                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>

                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>

                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                        <div class="pswp__preloader__cut">
                            <div class="pswp__preloader__donut"></div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div>
            </div>

            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>

            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>

            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>

        </div>

    </div>

</div>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.css">
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"></script>

<script>
    function viewer_init() {
        let pswpElement = document.querySelectorAll('.pswp')[0];
        let $imgArr = document.querySelectorAll(('.article-entry img:not(.reward-img)'))

        $imgArr.forEach(($em, i) => {
            $em.onclick = () => {
                // slider展开状态
                // todo: 这样不好，后面改成状态
                if (document.querySelector('.left-col.show')) return
                let items = []
                $imgArr.forEach(($em2, i2) => {
                    let img = $em2.getAttribute('data-idx', i2)
                    let src = $em2.getAttribute('data-target') || $em2.getAttribute('src')
                    let title = $em2.getAttribute('alt')
                    // 获得原图尺寸
                    const image = new Image()
                    image.src = src
                    items.push({
                        src: src,
                        w: image.width || $em2.width,
                        h: image.height || $em2.height,
                        title: title
                    })
                })
                var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, {
                    index: parseInt(i)
                });
                gallery.init()
            }
        })
    }
    viewer_init()
</script>




<script type="text/javascript" src="https://js.users.51.la/20544303.js"></script>
  </div>
</body>

</html>